package com.kunsan.compose.compoents.room

import android.Manifest
import android.app.Activity
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import com.kunsan.compose.ui.theme.RemoteUserBackground
import com.kunsan.compose.widget.ChatAppBar
import com.kunsan.compose.widget.ExitAction
import com.kunsan.compose.widget.RegularControlActions
import com.kunsan.compose.widget.ToggleCameraAction
import com.kunsan.compose.widget.ToggleMicrophoneAction
import com.kunsan.compose.widget.ToggleSpeakerAction
import com.kunsan.compose.widget.TwoVideoView
import com.kunsan.compose.widget.VideoCell
import io.agora.rtc2.ChannelMediaOptions
import io.agora.rtc2.Constants
import io.agora.rtc2.IRtcEngineEventHandler
import io.agora.rtc2.RtcEngine
import io.agora.rtc2.RtcEngineConfig
import io.agora.rtc2.video.VideoCanvas
import kotlinx.coroutines.launch


@Composable
fun RoomScreen(navController: NavController, viewModel: RoomViewModel = viewModel()) {

    val appId = "59c5ea27297140068da564cf5f9ef750"
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current
    val keyboard = LocalSoftwareKeyboardController.current
    var isJoined by rememberSaveable { mutableStateOf(false) }
    var channelName by rememberSaveable { mutableStateOf("kunsan") }
    var token by rememberSaveable { mutableStateOf("007eJxTYOBtjt6iWKadWiK9i+XOtMy80gnSsoorSgql1PLeOMq8e6PAYGqZbJqaaGRuZGluaGJgYGaRkmhqZpKcZppmmZpmbmpQ2rMpvSGQkeH6M31mRgYIBPHZGLJL84oT8xgYAKeyHhI=") }
    var localUid by rememberSaveable { mutableIntStateOf(0) }
    var remoteUid by rememberSaveable { mutableIntStateOf(0) }
    var reSetUpVideo by rememberSaveable { mutableStateOf(false) }
    var videoIdList by rememberSaveable { mutableStateOf(listOf<Int>()) }

    val scope = rememberCoroutineScope()
    val rtcEngine = remember {
        RtcEngine.create(RtcEngineConfig().apply {
            mContext = context
            mAppId = appId
            mEventHandler = object : IRtcEngineEventHandler() {
                override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
                    super.onJoinChannelSuccess(channel, uid, elapsed)

                    isJoined = true
                    localUid = uid
                    videoIdList = videoIdList + uid
                }

                override fun onLeaveChannel(stats: RtcStats?) {
                    super.onLeaveChannel(stats)
                    isJoined = false
                    videoIdList = emptyList()
//                    val s = navController.popBackStack()
                    scope.launch {
                        Log.e("房间事件", "onLeaveChannel")
                        navController.popBackStack()
                    }

                }

                override fun onUserJoined(uid: Int, elapsed: Int) {
                    super.onUserJoined(uid, elapsed)
                    videoIdList = videoIdList + uid
                    Log.e("房间事件", "onUserJoined $uid")
                    if (remoteUid == 0) {
                        remoteUid = uid
                    }
                }

                override fun onUserOffline(uid: Int, reason: Int) {
                    super.onUserOffline(uid, reason)
                    videoIdList = videoIdList - uid
                    if (uid == remoteUid) {
                        remoteUid = videoIdList.firstOrNull { it != localUid } ?: 0
                    }
                }


                override fun onVideoPublishStateChanged(
                    source: Constants.VideoSourceType?,
                    channel: String?,
                    oldState: Int,
                    newState: Int,
                    elapseSinceLastState: Int
                ) {
                    super.onVideoPublishStateChanged(
                        source,
                        channel,
                        oldState,
                        newState,
                        elapseSinceLastState
                    )
                    Log.e("房间事件", "onVideoPublishStateChanged $newState")

                    viewModel.updateVideoState(newState == Constants.PUB_STATE_NO_PUBLISHED)
                }

                override fun onAudioPublishStateChanged(
                    channel: String?,
                    oldState: Int,
                    newState: Int,
                    elapseSinceLastState: Int
                ) {
                    super.onAudioPublishStateChanged(
                        channel,
                        oldState,
                        newState,
                        elapseSinceLastState
                    )
                    Log.e("房间事件", "onAudioPublishStateChanged $newState")
                    if (newState == Constants.PUB_STATE_PUBLISHED) {
                        viewModel.updateAudioState(false)
                    } else if (newState == Constants.PUB_STATE_NO_PUBLISHED) {
                        viewModel.updateAudioState(true)
                    }
                }

                override fun onRemoteVideoStateChanged(uid: Int, state: Int, reason: Int, elapsed: Int) {
                    super.onRemoteVideoStateChanged(uid, state, reason, elapsed)

                }
            }
        }).apply {
            enableVideo()
        }
    }



    DisposableEffect(lifecycleOwner) {
        onDispose {
//            if (isJoined) {
//                rtcEngine.leaveChannel()
//            }
            RtcEngine.destroy()
        }
    }

    val permissionLauncher =
        rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestMultiplePermissions()) { grantedMap ->
            val allGranted = grantedMap.values.all { it }
            if (allGranted) {
                // Permission is granted
                Toast.makeText(context, "Permission Granted", Toast.LENGTH_LONG).show()
                val mediaOptions = ChannelMediaOptions()
                mediaOptions.channelProfile = Constants.CHANNEL_PROFILE_LIVE_BROADCASTING
                mediaOptions.clientRoleType = Constants.CLIENT_ROLE_BROADCASTER
                mediaOptions.publishMicrophoneTrack = true
                // 发布摄像头采集的视频
                mediaOptions.publishCameraTrack = true
                // 自动订阅所有音频流
                mediaOptions.autoSubscribeAudio = true
                // 自动订阅所有视频流
                mediaOptions.autoSubscribeVideo = true
                rtcEngine.joinChannel(token, channelName, 0, mediaOptions)

            } else {
                // Permission is denied
                Toast.makeText(context, "Permission Denied", Toast.LENGTH_LONG).show()
            }
        }

    LaunchedEffect(Unit) {
        permissionLauncher.launch(
            arrayOf(
                Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA
            )
        )
    }


    HorizontalPagedGrid(
        viewModel = viewModel,
        localUid = localUid,
        remoteUid = remoteUid,
        rtcEngine = rtcEngine,
        videoIdList = videoIdList,
        onPageChanged = {
            reSetUpVideo = true
            reSetUpVideo = false
        },
        setupVideo = { view, id, _ ->
            val canvas = VideoCanvas(view, Constants.RENDER_MODE_HIDDEN, id)
            if (id == localUid) {
                rtcEngine.setupLocalVideo(canvas)
            } else {
                rtcEngine.setupRemoteVideo(canvas)
            }
        }, reSetUpVideo = reSetUpVideo
    )

}


@Composable
fun HorizontalPagedGrid(
    viewModel: RoomViewModel,
    localUid: Int, remoteUid: Int, rtcEngine: RtcEngine? = null,
    videoIdList: List<Int>, setupVideo: (View, Int, Boolean) -> Unit,
    onPageChanged: (Int) -> Unit,
    overlay: @Composable BoxScope.(index: Int, id: Int?) -> Unit? = { _, _ -> },
    reSetUpVideo: Boolean
) {
    val pages = videoIdList.chunked(4)
    val isVideoMuted = viewModel.camera.collectAsState()
    val isAudioMuted = viewModel.microphone.collectAsState()

    val pagerState = rememberPagerState(pageCount = {
        2
    })
    Log.d("VideoCell", "HorizontalPagedGrid")

    val view = LocalView.current
    val window = (view.context as Activity).window

    Box {
        HorizontalPager(
            state = pagerState,
            modifier = Modifier.fillMaxSize(),
            beyondViewportPageCount = 0
        ) { pageIndex ->
            Log.d("VideoCell", "pageIndex = $pageIndex ${pagerState.currentPage}")

            if (pageIndex == 0) {
                Log.d("VideoCell渲染", "渲染第一页")

                TwoVideoView(
                    modifier = Modifier.fillMaxSize(),
                    localUid = localUid,
                    remoteUid = remoteUid,
                    secondClickable = false,
                    localPrimary = true,
                    localRender = { view, uid, isFirstSetup ->
                        rtcEngine?.setupLocalVideo(
                            VideoCanvas(
                                view,
                                Constants.RENDER_MODE_FIT,
                                uid
                            )
                        )
                        if (isFirstSetup) {
//                            rtcEngine?.startPreview()
                        }
                    },
                    remoteRender = { view, uid, isFirstSetup ->
                        rtcEngine?.setupRemoteVideo(
                            VideoCanvas(
                                view,
                                Constants.RENDER_MODE_FIT,
                                uid
                            )
                        )
                    },
                    reSetUpVideo = reSetUpVideo,
                    isVideoMuted = isVideoMuted.value,
                    isAudioMuted = isAudioMuted.value
                )


            } else {
                Log.d("VideoCell渲染", "渲染第二页")

                LazyVerticalGrid(
                    columns = GridCells.Fixed(2), // 每页2列
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(6.dp),
                    verticalArrangement = Arrangement.spacedBy(6.dp),
                    horizontalArrangement = Arrangement.spacedBy(6.dp)
                ) {
                    Log.d("VideoCell", "pages  ${pages.size} ${pageIndex}")

                    items(pages[pageIndex - 1].size, key = { pages[pageIndex - 1][it] }) { index ->
                        BoxWithConstraints(
                            modifier = Modifier
                                .fillMaxWidth()
                                .background(Color.Gray)
                                .aspectRatio(0.57f),
                            contentAlignment = Alignment.Center
                        ) {

                            VideoCell(
                                id = pages[pageIndex - 1][index],
                                setupVideo = setupVideo,
                                overlay = { overlay(1, pages[pageIndex - 1][index] ?: 0) },
                                isVideoMuted = isVideoMuted.value,
                                isAudioMuted = isAudioMuted.value,
                                background = RemoteUserBackground,
                                avatarSize = maxWidth / 2
                            )
                        }
                    }
                }
            }
        }
        BuildBottomControlBar(
            modifier = Modifier
                .align(Alignment.BottomCenter)
                .padding(bottom = 30.dp),
            viewModel = viewModel,
            rtcEngine = rtcEngine
        )
        ChatAppBar(modifier = Modifier.align(Alignment.TopCenter))
    }
}


@Composable
fun BuildBottomControlBar(modifier: Modifier, rtcEngine: RtcEngine?, viewModel: RoomViewModel) {
    val isMicrophoneMuted by viewModel.microphone.collectAsState()
    val isCameraMuted by viewModel.camera.collectAsState()
    val isSpeakerMuted by viewModel.speaker.collectAsState()

    RegularControlActions(
        modifier = modifier,
        spaceBy = 20.dp,
        actions = listOf(
            {
                ToggleSpeakerAction(
                    modifier = Modifier.size(
                        56.dp,
                    ),
                    isSpeakerMuted = isSpeakerMuted,
                    onCallAction = {
                        rtcEngine?.muteAllRemoteAudioStreams(it)
                    },
                )
            },
            {
                ToggleMicrophoneAction(
                    modifier = Modifier.size(
                        56.dp,
                    ),
                    isMicrophoneMuted = isMicrophoneMuted,
                    onCallAction = {
                        rtcEngine?.muteLocalAudioStream(it)
                    },
                )
            },
            {
                ToggleCameraAction(
                    modifier = Modifier.size(
                        56.dp,
                    ),
                    isCameraMuted = isCameraMuted,
                    onCallAction = {
                        if (it) {
                            rtcEngine?.stopPreview()
                        } else {
                            rtcEngine?.startPreview()
                        }
                        rtcEngine?.muteLocalVideoStream(it)
                    },
                )
            },
            {
                ExitAction(
                    modifier = Modifier.size(
                        56.dp,
                    ),
                    onCallAction = {
                        rtcEngine?.leaveChannel()
                    },
                )
            }
        )
    )
}

@Preview(showBackground = true)
@Composable
fun RoomScreenPreview() {
    RoomScreen(rememberNavController())
}